import tensorflow as tf
from tensorflow.keras import models, layers
import matplotlib.pyplot as plt
BATCH_SIZE = 32 #number of images in a batch
IMAGE_SIZE = 256
CHANNELS=3
EPOCHS=20
dataset = tf.keras.preprocessing.image_dataset_from_directory(
'./2specplants', # path to my datset (I used a subset of dataset for training and testing)
shuffle=True,
image_size=(IMAGE_SIZE,IMAGE_SIZE),
batch_size=BATCH_SIZE
)
Found 4627 files belonging to 5 classes.
#Different classes in dataset
class_names = dataset.class_names
class_names
['Pepper__bell___Bacterial_spot', 'Pepper__bell___healthy', 'Potato___Early_blight', 'Potato___Late_blight', 'Potato___healthy']
#number of classes
n_classes = len(class_names)
n_classes
5
for image_batch, labels_batch in dataset.take(1): #taking 1 item from dataset
print(image_batch.shape) # shows batch size, image dimension and channel(3 is for rgb)
print(labels_batch.numpy()) #labels corresponding to 32 images in the set
(32, 256, 256, 3) [3 0 0 1 1 0 3 0 2 1 0 3 2 2 2 1 0 1 0 2 0 3 2 3 0 0 2 1 0 1 3 3]
# vizualization of dataset
plt.figure(figsize=(15, 15))
for image_batch, labels_batch in dataset.take(1):
for i in range(12):
ax = plt.subplot(3, 4, i + 1)
plt.imshow(image_batch[i].numpy().astype("uint8"))
plt.title(class_names[labels_batch[i]])
plt.axis("off")
len(dataset)
145
#function to get train, test and validation data
# train size = 70% , validation size = 20% and testing size = 10%
def get_dataset_partitions_tf(ds, train_split=0.7, val_split=0.2, test_split=0.1, shuffle=True, shuffle_size=1000):
assert (train_split + test_split + val_split) == 1
ds_size = len(ds)
if shuffle:
ds = ds.shuffle(shuffle_size, seed=12)
train_size = int(train_split * ds_size)
val_size = int(val_split * ds_size)
train_ds = ds.take(train_size)
val_ds = ds.skip(train_size).take(val_size)
test_ds = ds.skip(train_size).skip(val_size)
return train_ds, val_ds, test_ds
train_ds, val_ds, test_ds = get_dataset_partitions_tf(dataset)
len(train_ds)
101
len(val_ds)
29
len(test_ds)
15
#performing cache and prefetch operations
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
val_ds = val_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
test_ds = test_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
#resizing the data for getting better accuracy
resize_and_rescale = tf.keras.Sequential([
layers.Resizing(IMAGE_SIZE, IMAGE_SIZE),
layers.Rescaling(1./255),
])
#data augmentation
data_augmentation = tf.keras.Sequential([
layers.RandomFlip("horizontal_and_vertical"),
layers.RandomRotation(0.2),
])
#Applying Data Augmentation to Train Dataset
train_ds = train_ds.map(
lambda x, y: (data_augmentation(x, training=True), y)
).prefetch(buffer_size=tf.data.AUTOTUNE)
BATCH_SIZE = 32 #number of images in a batch
IMAGE_SIZE = 256
CHANNELS=3
EPOCHS=20
#CNN architechture
input_shape = (BATCH_SIZE, IMAGE_SIZE, IMAGE_SIZE, CHANNELS)
model = models.Sequential([
resize_and_rescale,
data_augmentation,
layers.Conv2D(32, kernel_size = (3,3), activation='relu', input_shape=input_shape),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, kernel_size = (3,3), activation='relu'),
layers.MaxPooling2D((2, 2)),
# layers.Conv2D(64, (3, 3), activation='relu'),
# layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Flatten(),
layers.Dense(64, activation='relu'), #dense layer
layers.Dense(n_classes, activation='softmax'), #normalize the probability of ur classes
])
model.build(input_shape=input_shape)
model.summary()
Model: "sequential_11"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩ │ sequential_9 (Sequential) │ (32, 256, 256, 3) │ 0 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ sequential_10 (Sequential) │ (32, 256, 256, 3) │ 0 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ conv2d_16 (Conv2D) │ (32, 254, 254, 32) │ 896 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ max_pooling2d_16 (MaxPooling2D) │ (32, 127, 127, 32) │ 0 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ conv2d_17 (Conv2D) │ (32, 125, 125, 64) │ 18,496 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ max_pooling2d_17 (MaxPooling2D) │ (32, 62, 62, 64) │ 0 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ conv2d_18 (Conv2D) │ (32, 60, 60, 64) │ 36,928 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ max_pooling2d_18 (MaxPooling2D) │ (32, 30, 30, 64) │ 0 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ flatten_5 (Flatten) │ (32, 57600) │ 0 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ dense_10 (Dense) │ (32, 64) │ 3,686,464 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ dense_11 (Dense) │ (32, 5) │ 325 │ └──────────────────────────────────────┴─────────────────────────────┴─────────────────┘
Total params: 3,743,109 (14.28 MB)
Trainable params: 3,743,109 (14.28 MB)
Non-trainable params: 0 (0.00 B)
#compiling the model using adam optimizer and loss function used is log loss funnction, metrics is accuracy
model.compile(
optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['accuracy']
)
#train the network
history = model.fit(
train_ds,
batch_size=BATCH_SIZE,
validation_data=val_ds,
verbose=1,
epochs=EPOCHS, # for better accuracy pick a higher number
)
Epoch 1/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 152s 1s/step - accuracy: 0.3801 - loss: 1.7257 - val_accuracy: 0.6557 - val_loss: 0.9092 Epoch 2/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 89s 860ms/step - accuracy: 0.7329 - loss: 0.7342 - val_accuracy: 0.7464 - val_loss: 0.6974 Epoch 3/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 84s 821ms/step - accuracy: 0.7997 - loss: 0.5299 - val_accuracy: 0.7672 - val_loss: 0.7717 Epoch 4/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 84s 822ms/step - accuracy: 0.8610 - loss: 0.3787 - val_accuracy: 0.7847 - val_loss: 0.8449 Epoch 5/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 92s 903ms/step - accuracy: 0.8963 - loss: 0.2858 - val_accuracy: 0.8328 - val_loss: 0.6003 Epoch 6/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 109s 1s/step - accuracy: 0.9001 - loss: 0.2890 - val_accuracy: 0.8383 - val_loss: 0.5537 Epoch 7/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 117s 1s/step - accuracy: 0.9262 - loss: 0.2155 - val_accuracy: 0.8503 - val_loss: 0.5201 Epoch 8/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 100s 986ms/step - accuracy: 0.9204 - loss: 0.2503 - val_accuracy: 0.8393 - val_loss: 0.5530 Epoch 9/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 110s 1s/step - accuracy: 0.9426 - loss: 0.1724 - val_accuracy: 0.8689 - val_loss: 0.4801 Epoch 10/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 120s 1s/step - accuracy: 0.9393 - loss: 0.1663 - val_accuracy: 0.8995 - val_loss: 0.2858 Epoch 11/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 99s 977ms/step - accuracy: 0.9505 - loss: 0.1405 - val_accuracy: 0.9148 - val_loss: 0.3276 Epoch 12/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 94s 926ms/step - accuracy: 0.9487 - loss: 0.1365 - val_accuracy: 0.8809 - val_loss: 0.3489 Epoch 13/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 96s 943ms/step - accuracy: 0.9449 - loss: 0.1496 - val_accuracy: 0.9202 - val_loss: 0.2823 Epoch 14/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 100s 984ms/step - accuracy: 0.9569 - loss: 0.1215 - val_accuracy: 0.9563 - val_loss: 0.1616 Epoch 15/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 86s 848ms/step - accuracy: 0.9655 - loss: 0.1052 - val_accuracy: 0.9727 - val_loss: 0.0924 Epoch 16/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 86s 851ms/step - accuracy: 0.9467 - loss: 0.1241 - val_accuracy: 0.9246 - val_loss: 0.2557 Epoch 17/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 84s 828ms/step - accuracy: 0.9465 - loss: 0.1554 - val_accuracy: 0.8852 - val_loss: 0.3966 Epoch 18/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 97s 950ms/step - accuracy: 0.9643 - loss: 0.1058 - val_accuracy: 0.9716 - val_loss: 0.0763 Epoch 19/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 96s 942ms/step - accuracy: 0.9624 - loss: 0.1200 - val_accuracy: 0.9366 - val_loss: 0.1794 Epoch 20/20 101/101 ━━━━━━━━━━━━━━━━━━━━ 93s 917ms/step - accuracy: 0.9706 - loss: 0.0829 - val_accuracy: 0.9421 - val_loss: 0.1877
scores = model.evaluate(test_ds)
15/15 ━━━━━━━━━━━━━━━━━━━━ 20s 295ms/step - accuracy: 0.9539 - loss: 0.1494
scores #loss,accuracy
[0.19838659465312958, 0.9437500238418579]
history.params
{'verbose': 1, 'epochs': 20, 'steps': 101}
history.history.keys()
dict_keys(['accuracy', 'loss', 'val_accuracy', 'val_loss'])
len(history.history['loss'])
20
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
#Plotting graphs b/w training and validation accuracy
plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(range(EPOCHS), acc, label='Training Accuracy')
plt.plot(range(EPOCHS), val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training vs Validation Accuracy')
#Plotting graphs b/w training and validation loss
plt.subplot(1, 2, 2)
plt.plot(range(EPOCHS), loss, label='Training Loss')
plt.plot(range(EPOCHS), val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training vs Validation Loss')
plt.show()
#Testing model on a sample image
import numpy as np
for images_batch, labels_batch in test_ds.take(1):
first_image = images_batch[0].numpy().astype('uint8')
first_label = labels_batch[0].numpy()
print("first image to predict")
plt.imshow(first_image)
print("actual label:",class_names[first_label])
batch_prediction = model.predict(images_batch)
print("predicted label:",class_names[np.argmax(batch_prediction[0])])
first image to predict actual label: Potato___Late_blight 1/1 ━━━━━━━━━━━━━━━━━━━━ 1s 723ms/step predicted label: Potato___Late_blight
#sample image 2
for images_batch, labels_batch in test_ds.take(1):
first_image = images_batch[0].numpy().astype('uint8')
first_label = labels_batch[0].numpy()
print("first image to predict")
plt.imshow(first_image)
print("actual label:",class_names[first_label])
batch_prediction = model.predict(images_batch)
print("predicted label:",class_names[np.argmax(batch_prediction[0])])
first image to predict actual label: Pepper__bell___Bacterial_spot 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 263ms/step predicted label: Pepper__bell___Bacterial_spot
#creating a predict function for testing on sample inputs
def predict(model, img):
img_array = tf.keras.preprocessing.image.img_to_array(images[i].numpy())
img_array = tf.expand_dims(img_array, 0)
predictions = model.predict(img_array)
predicted_class = class_names[np.argmax(predictions[0])]
confidence = round(100 * (np.max(predictions[0])), 2) #confidence level calculation
return predicted_class, confidence
plt.figure(figsize=(15, 15))
for images, labels in test_ds.take(1):
for i in range(9):
ax = plt.subplot(3, 3, i + 1)
plt.imshow(images[i].numpy().astype("uint8"))
predicted_class, confidence = predict(model, images[i].numpy())
actual_class = class_names[labels[i]]
plt.title(f"Actual: {actual_class},\n Predicted: {predicted_class}.\n Confidence: {confidence}%")
plt.axis("off")
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 360ms/step 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 62ms/step 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 78ms/step 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 63ms/step 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 48ms/step 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 49ms/step 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 60ms/step 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 47ms/step 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 47ms/step